using System.Configuration;
using System.Data;
using System.Data.Common;

namespace MVP.DataAccess
{
    public class DatabaseConnection : IDatabaseConnection
    {
        private const string DATABASE_CONNECTION_CONFIG_KEY = "DatabaseConnection";
        private ConnectionInformation connectionInformation;
        private IDbConnection underlyingConnection;

        private class ConnectionInformation
        {
            private DbProviderFactory providerFactory;
            private ConnectionStringSettings settings;

            public ConnectionInformation(ConnectionStringSettings settings)
            {
                this.providerFactory = DbProviderFactories.GetFactory(settings.ProviderName);
                this.settings = settings;
            }

            public IDbConnection CreateConnection()
            {
                IDbConnection connection = providerFactory.CreateConnection();
                connection.ConnectionString = settings.ConnectionString;
                return connection;
            }
        }

        public DatabaseConnection()
        {
            InitializeConnectionInformation();
            OpenUnderlyingConnection();
        }

        private void OpenUnderlyingConnection()
        {
            underlyingConnection = connectionInformation.CreateConnection();
            underlyingConnection.Open();
        }

        public void Close()
        {
            underlyingConnection.Close();
        }

        private void InitializeConnectionInformation()
        {
            connectionInformation =
                new ConnectionInformation(
                    ConfigurationManager.ConnectionStrings[
                        ConfigurationManager.AppSettings[DATABASE_CONNECTION_CONFIG_KEY]]);
        }

        public void Dispose()
        {
            Close();
            underlyingConnection.Dispose();
            underlyingConnection = null;
        }

        public IDbConnection UnderlyingConnection
        {
            get { return underlyingConnection; }
        }

        public IDbCommand CreateCommandFor(string dynamicSqlExpression)
        {
            IDbCommand command = underlyingConnection.CreateCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = dynamicSqlExpression;
            return command;
        }
    }
}